package cn.wyz.user.service.impl;

import cn.wyz.basic.constants.BaseConstants;
import cn.wyz.basic.dto.RegisterDto;
import cn.wyz.basic.exception.BusinessException;
import cn.wyz.basic.util.MD5Utils;
import cn.wyz.basic.util.StrUtils;
import cn.wyz.user.domain.Logininfo;
import cn.wyz.user.domain.User;
import cn.wyz.user.mapper.LogininfoMapper;
import cn.wyz.user.mapper.UserMapper;
import cn.wyz.user.service.IUserService;
import cn.wyz.basic.service.impl.BaseServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.sql.Struct;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author WuyuZ
 * @since 2022-06-16
 */
@Service
public class UserServiceImpl extends BaseServiceImpl<User> implements IUserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private LogininfoMapper logininfoMapper;
    /**
     * 手机注册
     * 1.空校验
     * 2.短信验证码时限判断,
     *      2.1没拿到过期:throw重新获取
     *      2.2拿到往下
     * 3.判断拿到的旧smsCode与新传进来的是否一致
     *      3.1 不一致,重新输
     *      3.2 一致,那么进行新增
     * 4.保存数据,同时要对 t_user t_logininfo进行级联操作
     * @param dto
     */
    @Override
    public void phoneRegis(RegisterDto dto) {
        //1.1空校验,对象:手机号,随机验证码,密码及二次密码不为空
        String phone = dto.getPhone();
        String smsCode = dto.getSmsCode();
        String password = dto.getPassword();
        String passwordRepeat = dto.getPasswordRepeat();
        if(StringUtils.isEmpty(phone) ||
                StringUtils.isEmpty(smsCode) ||
                StringUtils.isEmpty(password) ||
                StringUtils.isEmpty(passwordRepeat)){
            throw new BusinessException("参数不能为空值");
        }
        //1.2密码和确认密码是否一致
        if(!password.equals(passwordRepeat)){
            throw new BusinessException("两次输入的密码要一致哦");
        }
        //2.短信验证码判断,现在redis中拿到,注册前缀+phone incomingKey:前端传入的key拼接前缀
        String incomingKey = BaseConstants.RegisterConstants.REGISTER_SMS_PREFIX + phone;
        //2.1通过前端传回key查询value
        Object oldSmsCode = redisTemplate.opsForValue().get(incomingKey);
        //如果拿不到  验证码过期，请重新获取
        if(oldSmsCode == null){
            throw new BusinessException("短信验证码已过期,请重新获取");
        }
        //3.判断拿到的旧smsCode与新传进来smsCode的是否一致
        if(!smsCode.equalsIgnoreCase(oldSmsCode.toString().split(":")[0])){
            throw new BusinessException("输入的短信验证码错误,请重新输入");
        }
//----------------------------  以上是对短信验证码进行校验,下面是保存操作   -------------------------------------
        //4.保存数据,学习思路:把类型强转,同时使用beansUtil提供的方法,同属性值拷贝
        User user = dto2User(dto);
        Logininfo logininfo =user2Logininfo(user);
        logininfoMapper.insert(logininfo);
        user.setLogininfoId(logininfo.getId());
        userMapper.insert(user);
    }

    private User dto2User(RegisterDto dto) {
        User user = new User();
        //3.手机号注册,就用手机号做用户名
        user.setUsername(dto.getPhone());
        user.setPhone(dto.getPhone());
        //1要手动设置盐值
        String salt = StrUtils.getComplexRandomString(32);
        user.setSalt(salt);
        //2对密码加密以后再存进user
        String password = MD5Utils.encrypByMd5(salt + dto.getPassword());
        user.setPassword(password);
        return user;
    }

    private Logininfo user2Logininfo(User user) {
        Logininfo logininfo = new Logininfo();
        BeanUtils.copyProperties(user,logininfo);
        //手动对t_logininfo表中的type(权限)设置,设置用户,不能直接给默认值
        logininfo.setType(1);
        return logininfo;
    }

    /*
      user的CUD  都需要级联操作logininfo
     */

    @Override
    public void update(User user) {
        Logininfo logininfo = logininfoMapper.selectById(user.getLogininfoId());
        BeanUtils.copyProperties(user,logininfo);
        logininfoMapper.update(logininfo);
        userMapper.update(user);
    }

    @Override
    public void deleteById(Long id) {
        User user = userMapper.selectById(id);
        logininfoMapper.deleteById(user.getLogininfoId());
        userMapper.deleteById(id);
    }

}
